package com.best.oasis.settlement.service.system;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.best.oasis.settlement.common.entity.system.MenuItem;
import com.best.oasis.settlement.common.enums.security.RoleType;
import com.best.oasis.settlement.common.vo.security.RoleVO;
import com.best.oasis.settlement.common.vo.security.UserVO;
import com.best.oasis.settlement.common.vo.system.MenuItemVO;
import com.best.oasis.settlement.dao.system.MenuItemDao;
import com.best.oasis.settlement.service.base.BaseServiceImpl;
import com.best.oasis.settlement.service.base.BusinessException;
import com.best.oasis.settlement.service.security.RoleService;
import com.best.oasis.settlement.service.security.UserService;
import com.best.oasis.settlement.util.page.BasePageSO;
import com.best.oasis.settlement.util.page.OrderType;
import com.best.oasis.util.tree.FlatTreeNode;
import com.best.oasis.util.tree.TreeNode;
import com.best.oasis.util.tree.TreeUtil;
import com.best.oasis.util.tree.Visitor;

@Service
public class MenuItemServiceImpl extends BaseServiceImpl<MenuItem, MenuItemVO, Long> implements MenuItemService {
	@Autowired
    private MenuItemDao menuItemDao;
	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	 
    @Override
    public void afterConstruct() {
        super.setBaseDao(menuItemDao);
        super.setEntityClass(MenuItem.class);
        super.setEntityVOClass(MenuItemVO.class);

    }

	/**
	 * 获取菜单树
	 */
    public TreeNode getMenuItemTree() {
    	
    	MenuItem root = menuItemDao.getRootMenu();	   
		BasePageSO so = new BasePageSO();
		so.addOrderField("sortIndex");
		so.setOrderType(OrderType.ASC);	
		List<MenuItem> allMenuItems=menuItemDao.getAll();		
		allMenuItems.add(root);
				
		List<FlatTreeNode> flatTreeNodeList = new ArrayList<FlatTreeNode>(allMenuItems.size() + 1);
		FlatTreeNode flatTreeNode;
		
		MenuItemVO nMenuItemVo;
		for (MenuItem menuItem : allMenuItems) {
			nMenuItemVo = new MenuItemVO();
			
			nMenuItemVo.setId(menuItem.getId());
			nMenuItemVo.setSortIndex(menuItem.getSortIndex());	//显示顺序
			nMenuItemVo.setName(menuItem.getName());			//菜单名称
			nMenuItemVo.setParentId(menuItem.getParentId());	//父菜单ID
			nMenuItemVo.setParentName(menuItem.getParentName());//父菜单名称
			nMenuItemVo.setRoleName(menuItem.getRoleName());	//权限名称
			nMenuItemVo.setTitle(menuItem.getTitle());			//显示在界面上的菜单标题
			nMenuItemVo.setLocation(menuItem.getLocation());	//菜单对应的模块路径
			nMenuItemVo.setDescription(menuItem.getDescription());//菜单描述说明
			
			flatTreeNode = new FlatTreeNode("" + menuItem.getId(), menuItem.getTitle(), "" + menuItem.getParentId(), nMenuItemVo);
			flatTreeNodeList.add(flatTreeNode);
		}
		//获取所有的菜单
		TreeNode menuItemTreeNodes = TreeUtil.buildTreeFromFlatTreeNodeList(""+ root.getId(), flatTreeNodeList, null);

        //获取当前登录用户
         UserVO loginUser=userService.getLoginUser();
         
		List<MenuItem> poList=menuItemDao.getMenuItemList(loginUser.getId());
		List<String> checkedNodeKeys=new ArrayList<String>();
		//获取当前用户对应的菜单权限
		for (MenuItem menuItem : poList){
			checkedNodeKeys.add(menuItem.getId().toString());
		}
		
		removeAllUncheckedNodes(menuItemTreeNodes, checkedNodeKeys);
						
        return menuItemTreeNodes;
    }
	/**
	 * 删除当前用户没有的菜单权限
	 */
	public  void removeAllUncheckedNodes(TreeNode root, List<String> checkedNodeKeys){
		//标记整棵树中存在的权限菜单
		TreeUtil.markCheckedNode(root, checkedNodeKeys);
		
		class DeleteNodeVisitor implements Visitor{
			public boolean visit(Object o) {
				TreeNode node = (TreeNode)o;
				List<TreeNode> removedChildren = new ArrayList<TreeNode>();
				if(node.getChildren() != null){
					for(TreeNode child : node.getChildren()){
						if(child.getCheckboxState() == 2 && !TreeUtil.isNodeHasDescendantChecked(child)){
							removedChildren.add(child);
						}
					}
					node.getChildren().removeAll(removedChildren);
				}
				return true;
			}
			
		}
		root.traverse(new DeleteNodeVisitor());		
	}
	
	
	@Override
	public List<MenuItemVO> getList() {
		List<MenuItemVO> roots = getAll();
		return roots;
	}

	@Override
	public List<MenuItemVO> saveOnEdit(List<MenuItemVO> list) {
		//数据库中原来有的menuItem
		List<MenuItemVO> oldList = getAll();
		//原列表有，新列表也有，但是部分值做了修改的
		List<MenuItemVO> editList = new ArrayList<MenuItemVO>();
		//原列表有，新列表没有，需要删除的
		List<MenuItemVO> deleteList = new ArrayList<MenuItemVO>();
		//原列表没有，新列表有的，需要增加的
		List<MenuItemVO> saveList = new ArrayList<MenuItemVO>();
		for (MenuItemVO oldVO : oldList){
			boolean flag = false;
			for(MenuItemVO newVO : list){
				if(newVO.getId() != null){
					if(newVO.getId().equals(oldVO.getId())){
						if(oldVO.getParentId() != null){
							if(newVO.getSortIndex() != oldVO.getSortIndex()
									|| !newVO.getParentId().equals(oldVO.getParentId())){
								editList.add(newVO);
							}
						} else {
							if(newVO.getParentId() != null || newVO.getSortIndex() != oldVO.getSortIndex()){
								editList.add(newVO);
							}
						}
						flag = true;
					}
				}
			}
			if(!flag){
				deleteList.add(oldVO);
			}
		}
		for (MenuItemVO newVO:list){
			if(newVO.getId() == null){
				saveList.add(newVO);
			}
		}
		List<MenuItemVO> result = new ArrayList<MenuItemVO>();
		
		if(saveList.size() > 0){
			result.addAll(save(saveList));
		}
		if(editList.size() > 0){
			result.addAll(edit(editList));
		}
		if(deleteList.size() > 0){
			delete(deleteList);
		}
		
		return result;
	}
	/**
	 * 保存
	 * @param saveList
	 * @return
	 */
	private List<MenuItemVO> save(List<MenuItemVO> saveList){
		List<MenuItemVO> result = new ArrayList<MenuItemVO>();
		
		for(MenuItemVO item : saveList){
			Long id = getNextSequence();
			item.setId(id);
			item.setVersion(0);
			item = create(item);
			result.add(item);
			saveRole(item);
		}
		
		return result;
	}
	/**
	 * 根据menuItem去新建一个role
	 */
	private RoleVO saveRole(MenuItemVO item ){
		RoleVO role = new RoleVO();
		role.setId(getNextSequence());
		role.setName(item.getRoleName());
		role.setRoleType(RoleType.FUNCTION);
		role.setDescription(item.getDescription());
		RoleVO parentRole = new RoleVO();
		MenuItemVO parentItem = get(item.getParentId());
		if(parentItem != null){
			parentRole = roleService.getBy("name", parentItem.getRoleName());
			if(parentRole != null){
				role.setParent(parentRole.getId());
			}
		}
		role = roleService.create(role);
		return role;
	}
	/**
	 * 编辑
	 * @param editList
	 * @return
	 */
	private List<MenuItemVO> edit(List<MenuItemVO> editList){
		
		List<MenuItemVO> result = new ArrayList<MenuItemVO>();
		
		for (MenuItemVO item : editList){
			//更新menuItem
			item = update(item);
			result.add(item);
			
			//更新role
			editRole(item);
			
		}
		return result;
	}
	/**
	 * 根据menuItem去更新相应的role
	 */
	private RoleVO editRole(MenuItemVO item){
		MenuItemVO parentItem = get(item.getParentId());
		RoleVO parentRole = new RoleVO();
		RoleVO role = roleService.getBy("name", item.getRoleName());
		if(parentItem != null){
			parentRole = roleService.getBy("name", parentItem.getRoleName());
		}
		if(role != null){
			if(role.getId() != null){
				role.setSortIndex(item.getSortIndex());
				if(parentRole != null){
					role.setParent(parentRole.getId());
				} else {//如果parentRole不存在，则将role的parentId设为0；
					//以免出现编辑角色时，生成的权限树只显示role
					role.setParent(new Long(0));
				}
			}
			role = roleService.update(role);
			return role;
		} else {
			return null;
		}
	}
	/**
	 * 删除
	 * @param deleteList
	 * @return
	 */
	private void delete(List<MenuItemVO> deleteList){
		for (MenuItemVO item : deleteList){
			deleteRole(item);
			remove(item.getId());
		}
	}
	
	/**
	 * 根据menuItem去删除相应的role
	 */
	private void deleteRole(MenuItemVO item){
		RoleVO role = roleService.getBy("name", item.getRoleName());
		if(role != null){
			boolean flag = roleService.checkByRole(role.getId());
			if(flag){
				throw new BusinessException("","菜单所关联的角色已被使用，删除失败。");
			}else{
				roleService.remove(role.getId());
			}
		}
	}
	
	
	private Long getNextSequence(){
		return menuItemDao.getNextSequence();
	}

}

